#include "usart.h"

USART_TypeDef* UART_Port;
uart_message_t uart_msg = {0};

void UART1_Serial_Init(uint32_t baud_rate)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	USART_InitTypeDef USART_InitStructure;
	USART_InitStructure.USART_BaudRate = baud_rate;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    
	USART_Init(USART1, &USART_InitStructure);
	
    USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);  //串口空闲时中断
	
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_Init(&NVIC_InitStructure);
	
	USART_Cmd(USART1, ENABLE);
    
    //DMA初始化
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);  // 使能 DMA1 时钟
    
    DMA_InitTypeDef DMA_InitStructure;
    DMA_InitStructure.DMA_BufferSize = BUFF_SIZE;                   // 定义了接收的最大长度
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;              // 串口接收，方向是外设->内存
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                    // 本次是外设到内存，所以关闭内存到内存
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)uart_msg.serial.payload;// 内存的基地址，要存储在哪里
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;// 内存数据宽度，按照字节存储
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;        // 内存递增，每次串口收到数据存在内存中，下次收到自动存储在内存的下一个位置
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                  // 正常模式
    DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_BASE + 0x04; // 外设的基地址，串口的数据寄存器
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;    // 外设的数据宽度，按照字节存储，与内存的数据宽度一致
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;   // 接收只有一个数据寄存器 RDR，所以外设地址不递增
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;            // 优先级
    DMA_Init(DMA_Channel_Serial, &DMA_InitStructure);
    
    USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);              //使能串口DMA接口
    DMA_Cmd(DMA_Channel_Serial, ENABLE);                        // 使能DMA接收
}

void UART2_Scanner_Init(uint32_t baud_rate)
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	USART_InitTypeDef USART_InitStructure;
	USART_InitStructure.USART_BaudRate = baud_rate;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    
	USART_Init(USART2, &USART_InitStructure);
	
    USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);  //串口空闲时中断
	
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_Init(&NVIC_InitStructure);
	
	USART_Cmd(USART2, ENABLE);
    
    //DMA初始化
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);  // 使能 DMA1 时钟
    
    DMA_InitTypeDef DMA_InitStructure;
    DMA_InitStructure.DMA_BufferSize = BUFF_SIZE;                   // 定义了接收的最大长度
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;              // 串口接收，方向是外设->内存
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                    // 本次是外设到内存，所以关闭内存到内存
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)uart_msg.scanner.payload;// 内存的基地址，要存储在哪里
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;// 内存数据宽度，按照字节存储
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;        // 内存递增，每次串口收到数据存在内存中，下次收到自动存储在内存的下一个位置
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                  // 正常模式
    DMA_InitStructure.DMA_PeripheralBaseAddr = USART2_BASE + 0x04; // 外设的基地址，串口的数据寄存器
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;    // 外设的数据宽度，按照字节存储，与内存的数据宽度一致
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;   // 接收只有一个数据寄存器 RDR，所以外设地址不递增
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;            // 优先级
    DMA_Init(DMA_Channel_Scanner, &DMA_InitStructure);
    
    USART_DMACmd(USART2, USART_DMAReq_Rx, ENABLE);              //使能串口DMA接口
    DMA_Cmd(DMA_Channel_Scanner, ENABLE);                        // 使能DMA接收
}

void UART3_RS485_Init(uint32_t baud_rate)
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

	USART_InitTypeDef USART_InitStructure;
	USART_InitStructure.USART_BaudRate = baud_rate;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    
	USART_Init(USART3, &USART_InitStructure);
    
    USART_ITConfig(USART3, USART_IT_IDLE, ENABLE);  //串口空闲时中断
	
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
    NVIC_Init(&NVIC_InitStructure);
	
	USART_Cmd(USART3, ENABLE);
    
    //DMA初始化
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);  // 使能 DMA1 时钟
    
    DMA_InitTypeDef DMA_InitStructure;
    DMA_InitStructure.DMA_BufferSize = BUFF_SIZE;                   // 定义了接收的最大长度
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;              // 串口接收，方向是外设->内存
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                    // 本次是外设到内存，所以关闭内存到内存
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)uart_msg.rs485.payload;// 内存的基地址，要存储在哪里
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;// 内存数据宽度，按照字节存储
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;        // 内存递增，每次串口收到数据存在内存中，下次收到自动存储在内存的下一个位置
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                  // 正常模式
    DMA_InitStructure.DMA_PeripheralBaseAddr = USART3_BASE + 0x04; // 外设的基地址，串口的数据寄存器
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;    // 外设的数据宽度，按照字节存储，与内存的数据宽度一致
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;   // 接收只有一个数据寄存器 RDR，所以外设地址不递增
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;            // 优先级
    DMA_Init(DMA_Channel_RS485, &DMA_InitStructure);
    
    USART_DMACmd(USART3, USART_DMAReq_Rx, ENABLE);              //使能串口DMA接口
    DMA_Cmd(DMA_Channel_RS485, ENABLE);                        // 使能DMA接收
}

void UART_SendByte(uint8_t Byte)
{
	USART_SendData(UART_Port, Byte);
	while (USART_GetFlagStatus(UART_Port, USART_FLAG_TXE) == RESET);
}

void UART_SendArray(USART_TypeDef* Port, uint8_t *Array, uint16_t Length)
{
	UART_Port = Port;
	for (uint16_t i = 0; i < Length; i ++)
	{
		UART_SendByte(Array[i]);
	}
}

int fputc(int ch, FILE *f)
{
	UART_SendByte(ch);
	return ch;
}

void UART_Printf(USART_TypeDef* Port, char *format, ...)
{
	char String[128];
	
	UART_Port = Port;
	va_list arg;
	va_start(arg, format);
	vsprintf(String, format, arg);
	va_end(arg);
	for (uint8_t i = 0; String[i] != '\0'; i ++)
	{
		UART_SendByte(String[i]);
	}
}

uint8_t Serial_Get(void)
{
    uint8_t flag = uart_msg.serial.complete;
    uart_msg.serial.complete = 0;
    return flag;
}
uint8_t Scanner_Get(void)
{
    uint8_t flag = uart_msg.scanner.complete;
    uart_msg.scanner.complete = 0;
    return flag;
}
uint8_t RS485_Get(void)
{
    uint8_t flag = uart_msg.rs485.complete;
    uart_msg.rs485.complete = 0;
    return flag;
}

void USART1_IRQHandler(void)
{    
    if(USART_GetITStatus(USART1, USART_IT_IDLE) == SET)    //一帧数据接收完成
    {
        //清空空闲中断
        USART1->SR;
        USART1->DR;
        
        DMA_Cmd(DMA_Channel_Serial, DISABLE);   //关闭DMA
        uart_msg.serial.complete = 1;           //置位完成标志
        uart_msg.serial.length = BUFF_SIZE - DMA_GetCurrDataCounter(DMA_Channel_Serial);    //计算数据长度
        DMA_SetCurrDataCounter(DMA_Channel_Serial, BUFF_SIZE);  //重载DMA计数
        DMA_Cmd(DMA_Channel_Serial, ENABLE);    //重启DMA
    }
}
void USART2_IRQHandler(void)
{    
    if(USART_GetITStatus(USART2, USART_IT_IDLE) == SET)    //一帧数据接收完成
    {
        //清空空闲中断
        USART2->SR;
        USART2->DR;
        
        DMA_Cmd(DMA_Channel_Scanner, DISABLE);   //关闭DMA
        uart_msg.scanner.complete = 1;           //置位完成标志
        uart_msg.scanner.length = BUFF_SIZE - DMA_GetCurrDataCounter(DMA_Channel_Scanner);    //计算数据长度
        DMA_SetCurrDataCounter(DMA_Channel_Scanner, BUFF_SIZE);  //重载DMA计数
        DMA_Cmd(DMA_Channel_Scanner, ENABLE);    //重启DMA
    }
}
void USART3_IRQHandler(void)
{    
    if(USART_GetITStatus(USART3, USART_IT_IDLE) == SET)    //一帧数据接收完成
    {
        //清空空闲中断
        USART3->SR;
        USART3->DR;
        
        DMA_Cmd(DMA_Channel_RS485, DISABLE);   //关闭DMA
        uart_msg.rs485.complete = 1;           //置位完成标志
        uart_msg.rs485.length = BUFF_SIZE - DMA_GetCurrDataCounter(DMA_Channel_RS485);    //计算数据长度
        DMA_SetCurrDataCounter(DMA_Channel_RS485, BUFF_SIZE);  //重载DMA计数
        DMA_Cmd(DMA_Channel_RS485, ENABLE);    //重启DMA
    }
}
